/*
 *所有关于measureinfo类的业务代码应在此处编写
*可使用repository.调用常用方法，获取EF/Dapper等信息
*如果需要事务请使用repository.DbContextBeginTransaction
*也可使用DBServerProvider.手动获取数据库相关信息
*用户信息、权限、角色等使用UserContext.Current操作
*measureinfoService对增、删、改查、导入、导出、审核业务代码扩展参照ServiceFunFilter
*/
using VOL.Core.BaseProvider;
using VOL.Core.Extensions.AutofacManager;
using VOL.Entity.DomainModels;
using System.Linq;
using VOL.Core.Utilities;
using System.Linq.Expressions;
using VOL.Core.Extensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http;
using VOL.RadarDevice.IRepositories;
using Newtonsoft.Json;
using VOL.Core.DbContext;
using AutoMapper;
using SqlSugar;
using VOL.Entity.DomainModels.Devices.Dto;
using System.Net;
using VOL.Core.Configuration;
using VOL.Core.ManageUser;
using Microsoft.Extensions.Options;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
using VOL.Entity.DomainModels.Devices.MongoDbModels;

namespace VOL.RadarDevice.Services
{
    public partial class measureinfoService
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly ImeasureinfoRepository _repository;//访问数据库
        private readonly IdeviceShareRepository _repositorySharp;//访问数据库
        private readonly MongoDbContext _mongoDbContext;
        private readonly IMapper _mapper;
        WebResponseContent webResponse = new WebResponseContent();

        [ActivatorUtilitiesConstructor]
        public measureinfoService(
            IMapper mapper,
            MongoDbContext mongoDbContext,
            ImeasureinfoRepository dbRepository,
            IdeviceShareRepository repositorySharp,
            IHttpContextAccessor httpContextAccessor
            )
        : base(dbRepository)
        {
            _httpContextAccessor = httpContextAccessor;
            _repository = dbRepository;
            _repositorySharp = repositorySharp;
            _mongoDbContext = mongoDbContext;
            _mapper = mapper;
            //多租户会用到这init代码，其他情况可以不用
            //base.Init(dbRepository);
        }
        /// <summary>
        /// 列表查询
        /// </summary>
        /// <param name="options"></param>
        /// <returns></returns>
        public override PageGridData<measureinfo> GetPageData(PageDataOptions options)
        {
            var deviceNo = "";
            var alarmFlag = "";
            DateTime? startTime = null;
            DateTime? endTime = null;

            var listWhere = JsonConvert.DeserializeObject<List<OptionWheres>>(options.Wheres);
            foreach (var item in listWhere)
            {
                if (item.name == "deviceNo")
                    deviceNo = item.value;
                else if (item.name == "alarmFlag")
                    alarmFlag = item.value;
                else if (item.name == "uploadTime" && item.displayType == "thanorequal")
                    startTime = DateTime.Parse(item.value);
                else if (item.name == "uploadTime" && item.displayType == "lessorequal")
                    endTime = DateTime.Parse(item.value);
            }

            int pageSize = options.Rows; // 每页显示的数量
            int pageIndex = options.Page; // 当前页码

            PageGridData<measureinfo> pageGridData = new PageGridData<measureinfo>();

            IEnumerable<MeasureInfo> querys2 = null;
            ISugarQueryable<measureinfo> querys = null;
            bool isUserMongo = false;
            if (startTime.HasValue && startTime.Value.AddDays(3) > DateTime.Now)
            {
                isUserMongo = true;
                querys2 = _mongoDbContext.MeasureInfo.WhereIF(!string.IsNullOrEmpty(deviceNo), m => m.deviceNo.Contains(deviceNo))
               .WhereIF(!string.IsNullOrEmpty(alarmFlag), m => m.alarmFlag == int.Parse(alarmFlag))
               .WhereIF(startTime.HasValue, m => m.uploadTimeOffset >= new DateTimeOffset(startTime.Value))
               .WhereIF(endTime.HasValue, m => m.uploadTimeOffset <= new DateTimeOffset(endTime.Value));

                var allowIds = AppSetting.QueryAllDeviceUserIds;
                if (!string.IsNullOrWhiteSpace(allowIds))
                {
                    var userId = UserContext.Current.UserId;
                    var strIds = allowIds.Split(',');
                    var ids = Array.ConvertAll(strIds, int.Parse);
                    if (!ids.Contains(userId))
                    {
                        var sharpModels = _repositorySharp.FindAsIQueryable(r => 1 == 1).ToList();
                        List<deviceShare> shares = new List<deviceShare>();
                        foreach (var sharpModel in sharpModels)
                        {
                            var userIds = sharpModel.shareUserIds.Split(",");
                            if (userIds.Contains(userId.ToString()))
                            {
                                shares.Add(sharpModel);
                            }
                        }
                        var deviceNoList = shares.Select(r => r.deviceNo).ToList();
                        querys2 = querys2.Where(d => d.CreateID == userId || deviceNoList.Contains(d.deviceNo));
                    }
                }
                pageGridData.total = querys2.ToList().Count;
            }
            else
            {
                querys = _repository.WhereIF(!string.IsNullOrEmpty(deviceNo), m => m.deviceNo.Contains(deviceNo))
                    .WhereIF(!string.IsNullOrEmpty(alarmFlag), m => m.alarmFlag == int.Parse(alarmFlag))
                    .WhereIF(startTime.HasValue, m => m.uploadTime >= startTime.Value)
                    .WhereIF(endTime.HasValue, m => m.uploadTime <= endTime.Value);

                var allowIds = AppSetting.QueryAllDeviceUserIds;
                if (!string.IsNullOrWhiteSpace(allowIds))
                {
                    var userId = UserContext.Current.UserId;
                    var strIds = allowIds.Split(',');
                    var ids = Array.ConvertAll(strIds, int.Parse);
                    if (!ids.Contains(userId))
                    {
                        var sharpModels = _repositorySharp.FindAsIQueryable(r => 1 == 1).ToList();
                        List<deviceShare> shares = new List<deviceShare>();
                        foreach (var sharpModel in sharpModels)
                        {
                            var userIds = sharpModel.shareUserIds.Split(",");
                            if (userIds.Contains(userId.ToString()))
                            {
                                shares.Add(sharpModel);
                            }
                        }
                        var deviceNoList = shares.Select(r => r.deviceNo).ToList();
                        querys = querys.Where(d => d.CreateID == userId || deviceNoList.Contains(d.deviceNo));
                    }
                }
                pageGridData.total = querys.ToList().Count;
            }
            if (isUserMongo)
            {
                var dtos = querys2;
                if (options.Order == "desc")
                    dtos = querys2.OrderByDescending(u => u.uploadTime).Skip((pageIndex - 1) * pageSize).Take(pageSize);
                else
                    dtos = querys2.OrderBy(u => u.uploadTime).Skip((pageIndex - 1) * pageSize).Take(pageSize);

                var models = dtos.ToList();
                foreach(var model in models)
                {
                    model.createTime = model.AddTime.LocalDateTime;
                    model.uploadTime = model.uploadTimeOffset.LocalDateTime;
                }
                var entitys = _mapper.Map<List<measureinfo>>(models);

                pageGridData.rows = entitys;
            }
            else
            {
                var dtos = querys;
                if (options.Order == "desc")
                    dtos = querys.OrderByDescending(u => u.uploadTime).Skip((pageIndex - 1) * pageSize).Take(pageSize);
                else
                    dtos = querys.OrderBy(u => u.uploadTime).Skip((pageIndex - 1) * pageSize).Take(pageSize);


                var models = dtos.ToList();
                var entitys = _mapper.Map<List<measureinfo>>(models);

                pageGridData.rows = entitys;
            }
           
            GetPageDataOnExecuted?.Invoke(pageGridData);
            return pageGridData;
        }
        /// <summary>
        /// 导出处理
        /// </summary>
        /// <param name="pageData"></param>
        /// <returns></returns>
        public override WebResponseContent Export(PageDataOptions pageData)
        {
            var deviceNo = "";
            var alarmFlag = "";
            DateTime? startTime = null;
            DateTime? endTime = null;

            var listWhere = JsonConvert.DeserializeObject<List<OptionWheres>>(pageData.Wheres);
            foreach (var item in listWhere)
            {
                if (item.name == "deviceNo")
                    deviceNo = item.value;
                else if (item.name == "alarmFlag")
                    alarmFlag = item.value;
                else if (item.name == "uploadTime" && item.displayType == "thanorequal")
                    startTime = DateTime.Parse(item.value);
                else if (item.name == "uploadTime" && item.displayType == "lessorequal")
                    endTime = DateTime.Parse(item.value);
            }

            IEnumerable<MeasureInfo> querys2 = null;
            ISugarQueryable<measureinfo> querys = null;
            List<measureinfo> entitys = null;
            bool isUserMongo = false;
            if (startTime.HasValue && startTime.Value.AddDays(1) > DateTime.Now)
            {
                isUserMongo = true;
                querys2 = _mongoDbContext.MeasureInfo.WhereIF(!string.IsNullOrEmpty(deviceNo), m => m.deviceNo.Contains(deviceNo))
               .WhereIF(!string.IsNullOrEmpty(alarmFlag), m => m.alarmFlag == int.Parse(alarmFlag))
               .WhereIF(startTime.HasValue, m => m.uploadTimeOffset >= new DateTimeOffset(startTime.Value))
               .WhereIF(endTime.HasValue, m => m.uploadTimeOffset <= new DateTimeOffset(endTime.Value));

                var allowIds = AppSetting.QueryAllDeviceUserIds;
                if (!string.IsNullOrWhiteSpace(allowIds))
                {
                    var userId = UserContext.Current.UserId;
                    var strIds = allowIds.Split(',');
                    var ids = Array.ConvertAll(strIds, int.Parse);
                    if (!ids.Contains(userId))
                    {
                        var sharpModels = _repositorySharp.FindAsIQueryable(r => 1 == 1).ToList();
                        List<deviceShare> shares = new List<deviceShare>();
                        foreach (var sharpModel in sharpModels)
                        {
                            var userIds = sharpModel.shareUserIds.Split(",");
                            if (userIds.Contains(userId.ToString()))
                            {
                                shares.Add(sharpModel);
                            }
                        }
                        var deviceNoList = shares.Select(r => r.deviceNo).ToList();
                        querys2 = querys2.Where(d => d.CreateID == userId || deviceNoList.Contains(d.deviceNo));
                    }
                }
                var dtos = querys2;
                if (pageData.Order == "asc")
                    dtos = querys2.OrderBy(u => u.uploadTime);
                else
                    dtos = querys2.OrderByDescending(u => u.uploadTime);

                var models = dtos.ToList();
                foreach (var model in models)
                {
                    model.createTime = model.AddTime.LocalDateTime;
                    model.uploadTime = model.uploadTimeOffset.LocalDateTime;
                }
                entitys = _mapper.Map<List<measureinfo>>(models);
            }
            else
            {
                querys = _repository.WhereIF(!string.IsNullOrEmpty(deviceNo), m => m.deviceNo.Contains(deviceNo))
                    .WhereIF(!string.IsNullOrEmpty(alarmFlag), m => m.alarmFlag == int.Parse(alarmFlag))
                    .WhereIF(startTime.HasValue, m => m.uploadTime >= startTime.Value)
                    .WhereIF(endTime.HasValue, m => m.uploadTime <= endTime.Value);

                var allowIds = AppSetting.QueryAllDeviceUserIds;
                if (!string.IsNullOrWhiteSpace(allowIds))
                {
                    var userId = UserContext.Current.UserId;
                    var strIds = allowIds.Split(',');
                    var ids = Array.ConvertAll(strIds, int.Parse);
                    if (!ids.Contains(userId))
                    {
                        var sharpModels = _repositorySharp.FindAsIQueryable(r => 1 == 1).ToList();
                        List<deviceShare> shares = new List<deviceShare>();
                        foreach (var sharpModel in sharpModels)
                        {
                            var userIds = sharpModel.shareUserIds.Split(",");
                            if (userIds.Contains(userId.ToString()))
                            {
                                shares.Add(sharpModel);
                            }
                        }
                        var deviceNoList = shares.Select(r => r.deviceNo).ToList();
                        querys = querys.Where(d => d.CreateID == userId || deviceNoList.Contains(d.deviceNo));
                    }
                }
                var dtos = querys;
                if (pageData.Order == "asc")
                    dtos = querys.OrderBy(u => u.uploadTime);
                else
                    dtos = querys.OrderByDescending(u => u.uploadTime);

                var models = dtos.ToList();
                entitys = _mapper.Map<List<measureinfo>>(models);
            }

            return base.MyExport(entitys);
        }
        public T ConvertTo<T>(object input)
        {
            return (T)Convert.ChangeType(input, typeof(T));
        }
        /// <summary>
        /// 查询测量信息(用于charts显示)
        /// </summary>
        /// <param name="MeasureQueryDto">查询实体</param>
        /// <returns></returns>
        public async Task<WebResponseContent> QueryMeasureCharts(MeasureQueryDto dto)
        {
            IEnumerable<MeasureInfo> querys2 = null;
            ISugarQueryable<measureinfo> querys = null;
            List<measureinfo> modelList = null;

            if (dto.startTime.HasValue && dto.startTime.Value.AddDays(1) > DateTime.Now)
            {
                querys2 = _mongoDbContext.MeasureInfo.Where(m => m.deviceNo == dto.deviceNo)
                   .WhereIF(dto.startTime.HasValue, m => m.uploadTimeOffset >= new DateTimeOffset(dto.startTime.Value))
                   .WhereIF(dto.endTime.HasValue, m => m.uploadTimeOffset <= new DateTimeOffset(dto.endTime.Value)).OrderBy(m => m.uploadTime);

                var list = querys2.ToList();
                foreach (var item in list)
                {
                    item.uploadTime = item.uploadTimeOffset.LocalDateTime;
                }
                modelList = _mapper.Map<List<measureinfo>>(list);
            }
            else
            {
                querys = repository.FindAsIQueryable(m => m.deviceNo == dto.deviceNo).WhereIF(dto.startTime.HasValue, m => m.uploadTime >= dto.startTime.Value)
                   .WhereIF(dto.endTime.HasValue, m => m.uploadTime <= dto.endTime.Value).OrderBy(m => m.uploadTime);
                modelList = querys.ToList();
            }
            
            int newAlarmFlag = 0;
            //var model =  await repository.FindAsIQueryable(m => m.deviceNo == dto.deviceNo).OrderBy(m => m.uploadTime).FirstAsync();//报警标志:1报警  2正常
            var model = _mongoDbContext.MeasureInfo.OrderBy(m => m.uploadTime).FirstOrDefault(m => m.deviceNo == dto.deviceNo);//报警标志:1报警  2正常
            if (model != null)
            {
                newAlarmFlag = (int)model.alarmFlag;
            }
            
            var timesListTemp = modelList.Select(m => m.uploadTime);
            int count = timesListTemp.Count();
            List<string> timesList = new List<string>();
            foreach (var item in timesListTemp)
            {
                #region mongodb使用
                //if (item.HasValue)
                //    timesList.Add(ConvertToLocalTime(item.Value));
                #endregion mongodb使用

                if (item != null)
                    timesList.Add(item.ToString("yyyy-MM-dd HH:mm:ss"));
                else
                    timesList.Add("");
            }

            var distance1 = modelList.Select(m => m.targetDistance1);
            var distance2 = modelList.Select(m => m.targetDistance2);
            var distance3 = modelList.Select(m => m.targetDistance3);
            var snr1 = modelList.Select(m => m.targetSnr1);
            var snr2 = modelList.Select(m => m.targetSnr2);
            var snr3 = modelList.Select(m => m.targetSnr3);
            var data = new
            {
                alarmFlag = newAlarmFlag,
                timesList = timesList,
                distance1 = distance1,
                distance2 = distance2,
                distance3 = distance3,
                snr1 = snr1,
                snr2 = snr2,
                snr3 = snr3,
            };

            return webResponse.OK(null, data);
        }

        public string ConvertToLocalTime(DateTime gmtTime)
        {
            // 假设GMT时间已经是UTC时间，如果不是，需要转换
            DateTime utcTime = DateTime.SpecifyKind(gmtTime, DateTimeKind.Utc);

            // 转换为本地时间
            DateTime localTime = utcTime.ToLocalTime();

            // 转换为字符串
            return localTime.ToString("yyyy-MM-dd HH:mm:ss");
        }
    }
}
